package LiuYun

import spinal.core._
import spinal.lib._

class CoreIn extends Bundle{
    val id    = UInt(9 bits)
    val intr  = UInt(8 bits)
    val ipi   = Bool()
    def setEmpty():Unit = {
        id   := U(0)
        intr := U(0)
        ipi  := False
    }
}

class CoreTop extends Component{
    val io = new Bundle{
        val core = in(new CoreIn)
        val axi  = master(new LabAxi3)
        val debug_wb:CoreDebug = out(new CoreDebug)
    }
    val s_fe1 = new StageFe1
    val s_fe2 = new StageFe2
    val s_de  = new StageDe
    val s_ex1 = new StageEx1
    val s_ex2 = new StageEx2
    val s_ex3 = new StageEx3
    val s_wb  = new StageWb
    val csr_file = new CsrFile
    val reg_file = new RegFile(2)
    val div = new Dividor(32)
    val itlb = new AddrTrans(LISA.TLB.FETCH)
    val dtlb = new AddrTrans(LISA.TLB.DATA)
    val l2tlb = new L2TLB
    val icache = new ICache
    val dcache = new DCache
    val arbiter = new LabAxi3Arbiter
    // val btb = new NoneBTB
    // val btb = new SimpleBTB
    // val btb = new NormalBTB
    val btb = new ComplexBTB
    // val btb = new C2BTB
    val difftest_inst = if( DifftestConfig.use_difftest) new DifftestInstrCommit(LISA.w_tlbidx) else null
    val difftest_excp = if( DifftestConfig.use_difftest) new DifftestExcpEvent else null
    val difftest_trap = if( DifftestConfig.use_difftest) new DifftestTrapEvent else null
    val difftest_store = if( DifftestConfig.use_difftest) new DifftestStoreEvent else null
    val difftest_load = if( DifftestConfig.use_difftest) new DifftestLoadEvent else null
    val difftest_csrreg = if( DifftestConfig.use_difftest) new DifftestCSRRegState else null
    val difftest_greg = if( DifftestConfig.use_difftest) new DifftestGRegState else null

    arbiter.io.axi <> io.axi
    icache.io.imiss <> arbiter.io.imiss
    dcache.io.dmiss <> arbiter.io.dmiss

    l2tlb.io.to.fe.l1_tlb <> itlb.io.from.l2_tlb
    l2tlb.io.to.data.l1_tlb <> dtlb.io.from.l2_tlb

    icache.io.isrch <> itlb.io.from.request
    icache.io.isrchresp <> itlb.io.to.response
    dcache.io.dsrch <> dtlb.io.from.request
    dcache.io.dsrchresp <> dtlb.io.to.response
    icache.io.l2srch <> l2tlb.io.from.fet_srch
    icache.io.l2srchresp <> l2tlb.io.to.fe.resp
    icache.io.l2will_resp <> l2tlb.io.to.fe.will_resp
    dcache.io.l2srch <> l2tlb.io.from.data_srch
    dcache.io.l2srchresp <> l2tlb.io.to.data.resp
    dcache.io.l2will_resp <> l2tlb.io.to.data.will_resp
    dcache.io.icop <> icache.io.icop

    s_fe1.io.ireq  <> icache.io.ireq
    s_fe2.io.iresp <> icache.io.iresp
    s_fe2.io.iexcpt:= icache.io.iexcpt

    s_de.io.r     <> reg_file.io.r


    s_ex1.io.tlbrw  <> l2tlb.io.from.rw
    s_ex1.io.invtlb <> l2tlb.io.from.inv
    s_ex1.io.addrtrans_ok <> s_ex2.io.addrtrans_ok

    s_ex1.io.dreq  <> dcache.io.dreq
    s_ex2.io.dexcpt<> dcache.io.dexcpt
    s_ex3.io.dresp <> dcache.io.dresp

    s_ex1.io.div   <> div.io.i
    s_ex3.io.div   <> div.io.o
    div.io.cancel  := csr_file.io.exbus.cancel

    s_wb .io.grw   <> reg_file.io.w

    s_fe1.io.brbus <> s_ex1.io.brbus
    s_fe2.io.brbus <> s_ex1.io.brbus
    s_de .io.brbus <> s_ex1.io.brbus
    l2tlb.io.core_control.br <> s_ex1.io.brbus

    s_fe1.io.exbus <> csr_file.io.exbus
    s_fe2.io.exbus <> csr_file.io.exbus
    s_de .io.exbus <> csr_file.io.exbus
    s_ex1.io.exbus <> csr_file.io.exbus
    s_ex2.io.exbus <> csr_file.io.exbus
    s_ex3.io.exbus <> csr_file.io.exbus
    l2tlb.io.core_control.ex <> csr_file.io.exbus

    s_de .io.fw(0) := s_ex1.io.fw
    s_de .io.fw(1) := s_ex2.io.fw
    s_de .io.fw(2) := s_ex3.io.fw
    s_de .io.fw(3) := s_wb .io.fw

    s_fe1.io.oc   <> s_fe2.io.ic
    s_fe1.io.odat <> s_fe2.io.idat
    s_fe2.io.oc   <> s_de .io.ic
    s_fe2.io.odat <> s_de .io.idat
    s_de .io.oc   <> s_ex1.io.ic
    s_de .io.odat <> s_ex1.io.idat
    s_ex1.io.oc   <> s_ex2.io.ic
    s_ex1.io.odat <> s_ex2.io.idat
    s_ex2.io.oc   <> s_ex3.io.ic
    s_ex2.io.odat <> s_ex3.io.idat
    s_ex3.io.oc   <> s_wb .io.ic
    s_ex3.io.odat <> s_wb .io.idat

    csr_file.io.wb <> s_wb.io.tocsr
    
    csr_file.io.core  <> io.core
    csr_file.io.totlb <> itlb.io.from.csr
    csr_file.io.totlb <> dtlb.io.from.csr
    csr_file.io.totlb <> l2tlb.io.csr
    csr_file.io.tofe  <> s_fe1.io.csr
    csr_file.io.tode  <> s_de.io.csr
    csr_file.io.toex  <> s_ex1.io.csr
    csr_file.io.rw    <> s_ex1.io.csrrw

    csr_file.io.tlbrd   <> l2tlb.io.to.rd
    csr_file.io.tlbsrch <> l2tlb.io.to.srch

    //s_ex1.io.tlbrw <> l2tlb.io.from.rw
    //s_ex1.io.invtlb <> l2tlb.io.from.inv

    btb.io.lookup <> s_fe1.io.btb
    btb.io.update <> s_ex1.io.btb
    s_fe1.io.ras <> btb.io.ras

    s_wb.io.debug <> io.debug_wb

    dcache.io.dmiss.araddr <> s_ex2.io.pa  //difftest
    l2tlb.io.tlbfill_index <> s_ex1.io.tlbfill_index //difftest
    if(DifftestConfig.use_difftest)
    {
    csr_file.io.difftest.estat <> s_ex1.io.csr_estat
    difftest_csrreg.io.diffcsrreg <> csr_file.io.difftest
    difftest_greg.io.diffgreg <> reg_file.io.difftest
    difftest_inst.io.diffinst <> s_wb.io.difftest_inst
    difftest_excp.io.diffexcp <> s_wb.io.difftest_excp
    difftest_load.io.diffload <> s_wb.io.difftest_load
    difftest_store.io.diffstore <> s_wb.io.difftest_store
    difftest_trap.io.difftrap <> s_wb.io.difftest_trap
    difftest_store.io.diffstore.valid(3).removeAssignments() := csr_file.io.difftest.llbctl(0) && RegNext(s_wb.io.tocsr.sc) && !RegNext(s_wb.io.tocsr.ex)
    //difftest_inst.io.diffinst.csr_data.removeAssignments() := csr_file.io.difftest.estat
    //difftest_excp.io.diffexcp.intrNo.removeAssignments() := csr_file.io.difftest.estat(12 downto 2)
    } else null

}
